<?php
/**
 * This file is part of Hyperf Mall.
 *
 * @link     https://gitee.com/scwlkj/hyperf_mall
 * @contact  hyperf_mall@163.com
 */

namespace App\Repository;


use App\Constants\Goods;
use App\Exception\BaseException;
use App\Model\BaseAttributeModel;
use App\Model\BaseAttributeValueModel;
use App\Utils\DB;
use Hyperf\Di\Annotation\Inject;
use PHPUnit\Exception;


class BaseAttributeRepository extends BaseRepository
{
    /**
     * @Inject
     * @var BaseAttributeModel
     */
    protected $model;

    /**
     * Notes: 列表
     * @param array $conditions
     * @param array $fields
     * @param int $page
     * @param int $size
     * @return array
     */
    public function getPageRows(array $conditions = [], array $fields = ['*'], int $page = 1, int $size = 10):array
    {
        $count = $this->_searchFactor($conditions)->count();

        $offset = max(0, ($page-1)*$size);
        $res = $this->_searchFactor($conditions)->offset($offset)->limit($size)->get($fields)->toArray();
        $ids = array_column($res, 'spec_ids');
        $attr_ids = array_column($res, 'id');
        $_ids = [];
        array_map(function ($val) use (&$_ids){
            if(!empty($val)){
                $_ids = array_merge($_ids, explode(',', $val));
            }
        }, $ids);

        if(!empty($_ids)){
            $_ids = array_unique($_ids);
            $spec = BaseSpecRepository::getInstance()->getRows(['id'=>$_ids],['id','title']);
            $spec = array_column($spec, null, 'id');
            foreach ($res as &$val){
                if(!empty($val['spec_ids'])){
                    $spec_name = [];
                    foreach (explode(',', $val['spec_ids']) as $value){
                        $spec_name[] = $spec[$value]['title'];
                    }

                    $val['spec_name'] = implode(',', $spec_name);
                }
            }
        }

        $attr = BaseAttributeValueRepository::getInstance()->getRows(['attribute_id'=>$attr_ids],['attribute_id','id','title']);

        foreach ($res as &$val){
            $attr_name = collect($attr)->where('attribute_id',$val['id'])->all();
            $val['attr_name'] = implode(',',array_column($attr_name, 'title') );
        }

        return ['total'=>$count, 'data'=>$res];
    }

    public function createAttr($data)
    {
        $attr = $data['attr_value'];
        unset($data['spec'], $data['attr_value']);

        DB::beginTransaction();
        try{
            $attr_model = $this->baseAdd($data);
            $attr_id = $attr_model['id'];

            $attr_value = [];
            array_map(function ($val) use (&$attr_value, $attr_id){
                $attr_value[] = [
                    'title'         =>$val['title'],
                    'sort'          =>$val['sort'],
                    'type'          =>$val['type_desc'],
                    'value'         =>$val['value'],
                    'attribute_id'  =>$attr_id,
                    'saas_id'       =>get_saas_id(),
                    'create_time'   =>time(),
                    'update_time'   =>time(),
                ];
            }, $attr);
            if(count($attr_value)) BaseAttributeValueModel::getInstance()->insert($attr_value);
            DB::commit();

            return true;
        }catch (Exception $exception){
            DB::rollBack();
            throw new BaseException(BaseException::BASE_ERROR, $exception->getMessage());
        }
    }

    /**
     * Notes: 详情
     * Author: Bruce.z
     * DateTime: 2022/1/13 16:08
     * @param int $id
     * @return array
     */
    public function detailAttr(int $id): array
    {
        $attr = $this->getOne(['id'=>$id]);
        if(!empty($attr['spec_ids'])){
            $ids = explode(',', $attr['spec_ids']);
            $attr['spec_value'] = BaseSpecRepository::getInstance()->getRows(['id'=>$ids],['title','id']);
        }

        $attr['attr_value'] = BaseAttributeValueRepository::getInstance()->getRows(['attribute_id'=>$id], ['title','value','type','sort','id']);

        return $attr;
    }

    public function updateAttr($id, $data)
    {
        $attr = $data['attr_value'];
        unset($data['attr_value']);

        DB::beginTransaction();
        try{
            $this->updateByConditions(['id'=>$id], $data);

            $attr_value = [];
            array_map(function ($val) use (&$attr_value, $id){
                if($val['id']){
                    $_data = [
                        'title'         =>$val['title'],
                        'value'         =>$val['value'],
                        'type'          =>$val['type'],
                        'sort'          =>$val['sort'],
                    ];
                    BaseAttributeValueRepository::getInstance()->updateByConditions(['id'=>$val['id']],$_data);
                }else{
                    $attr_value[] = [
                        'title'         =>$val['title'],
                        'sort'          =>$val['sort'],
                        'type'          =>$val['type'],
                        'value'         =>$val['value'],
                        'attribute_id'  =>$id,
                        'saas_id'       =>get_saas_id(),
                        'create_time'   =>time(),
                        'update_time'   =>time(),
                    ];
                }
            }, $attr);

            BaseAttributeValueModel::getInstance()
                ->where('attribute_id', $id)
                ->whereNotIn('id', array_column($attr, 'id'))
                ->delete();

            if(count($attr_value)) BaseAttributeValueModel::getInstance()->insert($attr_value);

            DB::commit();

            return true;
        }catch (Exception $exception){
            DB::rollBack();
            throw new BaseException(BaseException::BASE_ERROR, $exception->getMessage());
        }
    }

    public function deleteAttr(int $id)
    {
        DB::beginTransaction();
        try{
            $this->baseRemove($id);
            BaseAttributeValueModel::getInstance()
                ->where('attribute_id', $id)
                ->delete();

            DB::commit();

            return true;
        }catch (Exception $exception){
            DB::rollBack();
            throw new BaseException(BaseException::BASE_ERROR, $exception->getMessage());
        }
    }

    /**
     * Notes: 获取所有商品类型
     * DateTime: 2022/1/14 18:08
     * @return array
     */
    public function getAllAttr() : array
    {
        $res = $this->_searchFactor([])->get(['id','title','spec_ids'])->toArray();
        $ids = array_column($res, 'spec_ids');
        $attr_ids = array_column($res, 'id');
        $_ids = [];
        array_map(function ($val) use (&$_ids){
            if(!empty($val)){
                $_ids = array_merge($_ids, explode(',', $val));
            }
        }, $ids);

        if(!empty($_ids)){
            $_ids = array_unique($_ids);
            $spec = BaseSpecRepository::getInstance()->getRows(['id'=>$_ids],['id','title','show_type']);
            $spec = array_column($spec, null, 'id');
            $spec_value_id = array_column($spec, 'id');

            $spec_values = BaseSpecValueRepository::getInstance()->getRows(['spec_id'=>$spec_value_id], ['id','spec_id','title','data']);
            foreach ($res as &$val){
                if(!empty($val['spec_ids'])){
                    $spec_name = [];
                    foreach (explode(',', $val['spec_ids']) as $value){
                        $spec_name[] = $spec[$value]['title'];
                        $val['spec'][$value] = $spec[$value];
                        $val['spec'][$value]['spec_value'] = array_values(collect($spec_values)->where('spec_id',$value)->all());
                    }

                    $val['spec'] = array_values($val['spec']);
                    $val['spec_name'] = implode(',', $spec_name);
                }
            }
        }

        $attr = BaseAttributeValueRepository::getInstance()->getRows(['attribute_id'=>$attr_ids],['attribute_id','id','title','type','value']);
        foreach ($attr as &$val){
            if($val['type'] != Goods::STATUS_UP){
                $val['value'] = empty($val['value']) ? [] : explode(',', $val['value']);
                $val['select'] = [];
            }
        }

        foreach ($res as &$val){
            $val['attr'] = array_values(collect($attr)->where('attribute_id',$val['id'])->all());
        }

        return $res;
    }
}
